{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -*- coding: utf-8 -*-\n",
    "from miasm.analysis.machine import Machine\n",
    "from miasm.analysis.binary import Container\n",
    "from miasm.expression.expression import *\n",
    "from miasm.core.utils import *\n",
    "from miasm.core.locationdb import LocationDB\n",
    "from miasm.arch.x86 import regs\n",
    "from miasm.ir.symbexec import SymbolicExecutionEngine, get_block\n",
    "from miasm.expression.simplifications import expr_simp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!unzip -n -P infected zeusvm.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "filename = 'zeusvm.bin'\n",
    "\n",
    "machine = Machine('x86_32')\n",
    "loc_db = LocationDB()\n",
    "with open(filename, 'rb') as fstream:\n",
    "    cont = Container.from_stream(fstream, loc_db)\n",
    "bs = cont.bin_stream\n",
    "mdis = machine.dis_engine(bs, loc_db=cont.loc_db)\n",
    "ir_arch = machine.ir(mdis.loc_db)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "# Error\n",
    "mnemonic_array_addr = 0x427018\n",
    "\n",
    "for i in range(69):\n",
    "    # Get each handler address from the array\n",
    "    addr = int(hex(upck32(bs.getbytes(mnemonic_array_addr + i*4, 4))), 16)\n",
    "    print('*'*40, 'Mnemonic', i, ' addr', addr, '*'*40)\n",
    "    \n",
    "    # Generate AsmCFG and IRCFG\n",
    "    asmcfg = mdis.dis_multiblock(addr)\n",
    "    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)\n",
    "    irblock = ircfg.get_block(addr)\n",
    "    \n",
    "    # Initialize symbolic execution engine\n",
    "    sb = SymbolicExecutionEngine(ir_arch)\n",
    "    addr = sb.eval_updt_irblock(irblock)\n",
    "    if not isinstance(addr, ExprInt):\n",
    "        print('Unknown destination %s' % addr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Preparing the initial symbols for regs and mems\n",
    "symbols_init = dict(regs.regs_init)\n",
    "initial_symbols = symbols_init.items()\n",
    "ret_addr = ExprId('RET_ADDR', 32)\n",
    "vm_pc_init = ExprId('VM_PC_init', 32)\n",
    "infos = {}\n",
    "infos[expr_simp(ExprMem(regs.ECX_init, 32))] = vm_pc_init\n",
    "# Push return addr\n",
    "infos[expr_simp(ExprMem(regs.ESP_init-ExprInt(4, 32), 32))] = ret_addr\n",
    "infos[regs.ESP] = expr_simp(regs.ESP_init-ExprInt(4, 32))\n",
    "\n",
    "for i in range(0, 5):\n",
    "    infos[expr_simp(ExprMem(regs.ECX_init + ExprInt(4*(i+1), 32), 32))] = ExprId('REG%d' % i, 32)\n",
    "\n",
    "addition_infos = dict(infos)\n",
    "\n",
    "# imm\n",
    "expr_imm8 = expr_simp(ExprMem(vm_pc_init + ExprInt(0x1, 32), 8))\n",
    "addition_infos[expr_imm8] = ExprId('imm8' , 8)\n",
    "\n",
    "expr_imm16 = expr_simp(ExprMem(vm_pc_init + ExprInt(0x1, 32), 16))\n",
    "addition_infos[expr_imm16] = ExprId('imm16' , 16)\n",
    "\n",
    "expr_imm32 = expr_simp(ExprMem(vm_pc_init + ExprInt(0x1, 32), 32))\n",
    "addition_infos[expr_imm32] = ExprId('imm32' , 32)\n",
    "\n",
    "# immb\n",
    "expr_imm8b = expr_simp(ExprMem(vm_pc_init + ExprInt(0x2, 32), 8))\n",
    "addition_infos[expr_imm8b] = ExprId('imm8b' , 8)\n",
    "\n",
    "expr_imm16b = expr_simp(ExprMem(vm_pc_init + ExprInt(0x2, 32), 16))\n",
    "addition_infos[expr_imm16b] = ExprId('imm16b' , 16)\n",
    "\n",
    "expr_imm32b = expr_simp(ExprMem(vm_pc_init + ExprInt(0x2, 32), 32))\n",
    "addition_infos[expr_imm32b] = ExprId('imm32b' , 32)\n",
    "\n",
    "imms = set([expr_imm8, expr_imm16, expr_imm32,\n",
    "            expr_imm8b, expr_imm16b, expr_imm32b])\n",
    "\n",
    "imm8 = ExprId('imm8', 8)\n",
    "\n",
    "base_regx = expr_simp(regs.ECX_init + (imm8.zeroExtend(32) & ExprInt(0xF, 32)) * ExprInt(4, 32) + ExprInt(0xC, 32))\n",
    "addition_infos[expr_simp(ExprMem(base_regx, 32))] = ExprId('REGX' , 32)\n",
    "addition_infos[expr_simp(ExprMem(base_regx, 16))] = ExprId('REGX' , 32)[:16]\n",
    "addition_infos[expr_simp(ExprMem(base_regx, 8))] = ExprId('REGX' , 32)[:8]\n",
    "\n",
    "base_regy = expr_simp(regs.ECX_init + (imm8[4:8].zeroExtend(32)) * ExprInt(4, 32) + ExprInt(0xC, 32))\n",
    "addition_infos[expr_simp(ExprMem(base_regy, 32))] = ExprId('REGY' , 32)\n",
    "addition_infos[expr_simp(ExprMem(base_regy, 16))] = ExprId('REGY' , 16)[:16]\n",
    "addition_infos[expr_simp(ExprMem(base_regy, 8))] = ExprId('REGY' , 8)[:8]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def dump_state(sb):\n",
    "    print('-'*20, 'State', '-'*20)\n",
    "    out = {}\n",
    "    for expr, value in sorted(sb.symbols.items()):\n",
    "        if (expr, value) in initial_symbols:\n",
    "            continue\n",
    "        if (expr, value) in addition_infos:\n",
    "            continue\n",
    "        if expr in [regs.zf, regs.cf, regs.nf, regs.of, regs.pf, regs.af,\n",
    "                    ir_arch.IRDst, regs.EIP]:\n",
    "            continue\n",
    "        expr_s = expr_simp(expr.replace_expr(addition_infos))\n",
    "        expr = expr_s\n",
    "        value = expr_simp(value.replace_expr(addition_infos))\n",
    "        if expr == value:\n",
    "            continue\n",
    "        out[expr] = value\n",
    "\n",
    "    out = sorted(out.items())\n",
    "    x86_regs = []\n",
    "    mem = []\n",
    "    other = []\n",
    "    for expr, value in out:\n",
    "        if expr in regs.all_regs_ids:\n",
    "            x86_regs.append((expr, value))\n",
    "        elif isinstance(expr, ExprMem):\n",
    "            mem.append((expr, value))\n",
    "        else:\n",
    "            other.append((expr, value))\n",
    "\n",
    "    print('Regs:')\n",
    "    for item in other:\n",
    "        print('\\t%s = %s' % item)\n",
    "    print('Mem:')\n",
    "    for item in mem:\n",
    "        print('\\t%s = %s' % item)\n",
    "    print('x86:')\n",
    "    for item in x86_regs:\n",
    "        print('\\t%s = %s' % item)\n",
    "    print('')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "mnemonic_array_addr = 0x427018\n",
    "\n",
    "for i in range(69):\n",
    "    # Get each handler address from the array\n",
    "    addr = int(hex(upck32(bs.getbytes(mnemonic_array_addr + 4*i, 4))), 16)\n",
    "    print('*'*40, 'Mnemonic', i, ' addr', hex(addr), '*'*40)\n",
    "    \n",
    "    # Generate AsmCFG and IRCFG\n",
    "    asmcfg = mdis.dis_multiblock(addr)\n",
    "    ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)\n",
    "    irblock = ircfg.get_block(addr)\n",
    "        \n",
    "    # Initialize symbolic execution engine\n",
    "    sb = SymbolicExecutionEngine(ir_arch, symbols_init)\n",
    "    for k, v in infos.items():\n",
    "        sb.symbols[k] = v\n",
    "\n",
    "    symbols = frozenset(sb.symbols.items())\n",
    "    todo = set([(addr, symbols)])\n",
    "\n",
    "    count = 20\n",
    "    while todo and count > 0:\n",
    "        count -=1\n",
    "        \n",
    "        addr, symbols = todo.pop()\n",
    "        \n",
    "        irblock = ircfg.get_block(addr)    \n",
    "        if not irblock:\n",
    "            print(ValueError('Unknown destination %s' % addr))\n",
    "            continue\n",
    "\n",
    "        sb.symbols.symbols_id.clear()\n",
    "        sb.symbols.symbols_mem.clear()\n",
    "        for k, v in symbols:\n",
    "            sb.symbols[k] = v\n",
    "\n",
    "        print('Block', addr)\n",
    "        addr = sb.eval_updt_irblock(irblock)\n",
    "\n",
    "        sb.del_mem_above_stack(ir_arch.sp)\n",
    "\n",
    "        if addr is ret_addr:\n",
    "            print('Ret addr reached')\n",
    "            ret_mn = expr_simp(sb.eval_expr(regs.EAX[:8]))\n",
    "            if ret_mn != ExprInt(1, 8):\n",
    "                print('Strange return', ret_mn)\n",
    "            dump_state(sb)\n",
    "            continue\n",
    "\n",
    "        if isinstance(addr, ExprCond):\n",
    "            todo.add((addr.src1, frozenset(sb.symbols.items())))\n",
    "            todo.add((addr.src2, frozenset(sb.symbols.items())))\n",
    "            continue\n",
    "        if not isinstance(addr, ExprInt) or isinstance(addr, ExprId):\n",
    "            print('BAD END', addr)\n",
    "            break\n",
    "\n",
    "        todo.add((addr, frozenset(sb.symbols.items())))\n",
    "    if count == 0:\n",
    "        print('Mnemonic too complex')\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
